import Cocoa

//var str = "Hello, playground"

//函数的调用  函数的格式: func 函数名(形参: 形参类型) -> 返回值类型 {}
func greeting(person: String) -> String {
    return "hello" + person + "!"
}
//调用函数
greeting(person: " Lily")


//1.无形式参数的函数
func sayHelloWorld() -> String {
    return "hello world"
}
//调用函数
sayHelloWorld()

//2.有返回值有参数的函数(单一的形参)
func greetAgain(person: String) -> String {
    return "hello" + person + "!"
}
//调用函数
greetAgain(person: " Bob")

//有返回值有形参的函数(多形式参数)
func greet(person: String, alreadyGreet: Bool) -> String {
    if alreadyGreet {
        return  greetAgain(person: person)
    } else {
        return greeting(person: person)
    }
}
print(greet(person: " Lily", alreadyGreet: true))

//3.无返回值的函数
func greet2(person: String) {
    print("person is \(person)")
}
greet2(person: " 李梅")

//多返回值的函数
//获取数组中的最大值和最小值
//func minMax(array: [Int]) -> (min: Int, max: Int) {
//    if array.isEmpty {
//        return (0, 0)
//    }
//    var minValue = array[0]
//    var maxValue = array[0]
//    for value in array {
//        print("value is \(value)")
//        if value < minValue {
//            minValue = value
//        }
//        if value > maxValue {
//            maxValue = value
//        }
//    }
//    return (minValue, maxValue)
//}
//let value = minMax(array: [1, 2, 5, 10, 30, 4])
//print("minValue is \(value.min), maxValue is \(value.max)")


//4. 可选元组做为函数的返回值
func minMax(array: [Int]) -> (min: Int, max: Int)? {
    if array.isEmpty {
        return (0, 0)
    }
    var minValue = array[0]
    var maxValue = array[0]
    for value in array {
        print("value is \(value)")
        if value < minValue {
            minValue = value
        }
        if value > maxValue {
            maxValue = value
        }
    }
    return (minValue, maxValue)
}
let arr = minMax(array: [1, 3, 6, 19, 4])
//可选元组做完函数的返回值,只需要在获取值的时候解包就好了
if arr != nil {
    print("minValue is \(arr!.min), maxValue is \(arr!.max)")
}


//5. 隐式返回的函数:在函数名前面加上for,在调用函数的时候可以省略函数名,直接使用for就可以了
func greeting2(for person: String) -> String {
    return "hello" + person + "!"
}
//调用函数
greeting2(for: " 老王")



//6. 多个形参的函数
func addTwoNumber(number1: Int, number2: Int) -> Int {
    return number1 + number2
}
print(addTwoNumber(number1: 3, number2: 8))


//7. 添加实际参数标签
func addTwoNumber2(first num1: Int, second num2: Int) -> Int {
    return num1 + num2
}
//调用时只需要传入实际参数标签,不需要传入形式参数了
print(addTwoNumber2(first: 2, second: 7))


//8. 用通配符来省略实际参数标签
func addTwoNumber3(_ num1: Int, _ num2: Int) -> Int {
    return num1 + num2
}
//调用函数的时候可以连形式参数都不用传了,直接赋值
print(addTwoNumber3(8, 9))


//9. 可变形式参数,需要在变量类型后面插入三个点"...",表示形参的个数不确定,是一个数组
func addTwoNumber4(_ numbers: Double...) -> Double {
    var sum: Double = 0
    for num in numbers {
        sum += num
    }
    return sum / Double(numbers.count)  //这里需要强转成Double类型
}
print(addTwoNumber4(1, 2, 3, 4, 5))  //返回值是15.0, Double类型
print(addTwoNumber4(1.2, 3.4, 5.6))

//10. 输入输出形式参数:可以在函数外面修改形式参数的值(在形式参数前面加入inout)
var oneNumber = 8
var anotherNumber = 10
func swapValue(_ a: inout Int, _ b: inout Int) {   //没有返回值
    //交换两个变量的值
    let temp = a
    a = b
    b = temp
}
swapValue(&oneNumber, &anotherNumber)
print(oneNumber)
print(anotherNumber)

//定义一个函数,将之前的函数赋值给这个函数(输入输出形式参数也要带上)
var swapFunction:(inout Int, inout Int) -> () = swapValue
swapFunction(&oneNumber, &anotherNumber)
print("one is \(oneNumber), another is \(anotherNumber)")


func addTwoNumber6(num1: Int, num2: Int) -> Int {
    return num1 + num2
}

func multiplyTwoNumber(_ num1: Int, _ num2: Int) -> Int {
    return num1 * num2
}
//定义一个函数
//var mathFunction:(Int, Int) -> Int = addTwoNumber6
var mathFunction:(Int, Int) -> Int = multiplyTwoNumber
print(mathFunction(2, 3))




func addTwoInts(_ a: Int, _ b: Int) -> Int {
    return a + b
}

//函数类型作为形式参数类型
func printMathResult(_ mathFunction:(Int, Int) -> Int, a: Int, b: Int) {
    print("result: \(mathFunction(a, b))")
}
printMathResult(addTwoInts, a: 3, b: 5)
printMathResult(addTwoInts, a: 2, b: 9)


//函数类型作为返回类型
//前进的步数
func stepForward(_ input: Int) -> Int {
    return input + 1
}

//退后的步数
func stepBackward(_ input: Int) -> Int {
    return input - 1
}

func chooseStepFunction(backWard: Bool) -> (Int) -> Int {
    return backWard ? stepBackward : stepForward
}

var currentValue = -4
let moveNearerToZero = chooseStepFunction(backWard: currentValue > 0)
print(moveNearerToZero(9))

while currentValue != 0 {
    print("\(currentValue)...")
    currentValue = moveNearerToZero(currentValue)
}
print("value is \(currentValue)")


//内嵌函数
func chooseStepFunction2(backward: Bool) -> (Int) -> Int {
    func stepForward(_ input: Int) -> Int { return input + 1 }
    func stepBackward(_ input: Int) -> Int { return input - 1 }
    return backward ? stepBackward : stepForward
}
var currentValue2 = 3
var value = chooseStepFunction(backWard: currentValue2 > 0)
print(value(3))









